package com.declum.naduvar.locking;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

import com.declum.naduvar.locking.handler.LockingHandler;

/**
 * LockServer that encapsulate the Lock Handler with a Socket
 * 
 * @author clement
 * 
 */
public class LockServer {
	private static Logger logger;
	private static final int PORT = 9123;

	private static void printUsage(Options opts) {
		HelpFormatter formatter = new HelpFormatter();
		formatter.printHelp("LockServer", opts);
	}

	public static void main(String[] args) throws Exception {

		/**
		 * Configure the Logger object
		 */
		PropertyConfigurator.configure("log4jconfig.prp");
		
		/**
		 * Initialize the Logger
		 */
		logger = Logger.getLogger(LockServer.class);

		CommandLineParser parser = new GnuParser();

		Options opts = new Options();
		opts.addOption("d", "dir", true, "Specify working directory");
		opts
				.addOption("i", "interval", true,
						"Interval at which the lock has to be expired. It can only be a number");
		CommandLine line = null;

		try {
			line = parser.parse(opts, args);
		} catch (ParseException exp) {
			System.err.println("Parsing failed.  Reason: " + exp.getMessage());
		}
		String workingDirectory = null;
		String strDefaultLeaseInterval = null;
		int defaultLeaseInterval = 60000;

		if (line == null) {
			System.exit(-1);
			return;
		}
		workingDirectory = line.getOptionValue("d");
		if (workingDirectory == null) {
			printUsage(opts);
			System.exit(0);
			return;
		}

		strDefaultLeaseInterval = line.getOptionValue("i", "60000");
		try {
			defaultLeaseInterval = Integer.parseInt(strDefaultLeaseInterval);
		} catch (Exception e) {
			printUsage(opts);
		}

		/**
		 * Was not knowing why this is for
		 */
		ByteBuffer.setUseDirectBuffers(false);

		/**
		 * I think for Heap Allocation
		 */
		ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

		/**
		 * Create a Acceptor
		 */
		IoAcceptor acceptor = new SocketAcceptor();

		/**
		 * Create a SocketAccepterConfig to configure the Server Socket
		 */
		SocketAcceptorConfig cfg = new SocketAcceptorConfig();

		/**
		 * Add a logger hander in the Chain
		 */
		cfg.getFilterChain().addLast("logger", new LoggingFilter());

		/**
		 * Add the Text decoder/encoder to the chain, this processes the request
		 * and call LockHandler handler for each line
		 */
		cfg.getFilterChain().addLast(
				"codec",
				new ProtocolCodecFilter(new TextLineCodecFactory(Charset
						.forName("UTF-8"))));

		/**
		 * This is our Custom Handler for the Service
		 */
		LockingHandler lockingHandler = new LockingHandler();
		lockingHandler.setLeaseInterval(defaultLeaseInterval);
		lockingHandler.setWorkingDirectory(workingDirectory);
		lockingHandler.init();
		
		/**
		 * Bind the Server to a port
		 */
		acceptor.bind(new InetSocketAddress(PORT), lockingHandler, cfg);
		logger.debug("MINA Time server started.");
	}
}
